<?php
/**
 * 请求的封装
 *
 * @since 1.0
 * @package if
 * @subpackage controller.context
 */
class IRequest extends IObject {
	private static $instance;
	private $params = array();
	private $noFilterParamsHistory = array();
	private $noFilterParams = array();
	
	private function __construct() {
		
	}
	
	/**
	 * 取得类的单例
	 *
	 * @return IRequest
	 * @since 1.0
	 */
	static function singleton() {
		if (!self::$instance) {
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	/**
	 * 添加参数
	 *
	 * @param string $param 参数名
	 * @param mixed $value 参数值
	 * @since 1.0
	 */
	function addParam($param, $value) {
		//$this->params[$param] = $value;
		$this->params = if_array_set($this->params, $param, $value);
	}
	
	/**
	 * 添加一组参数
	 *
	 * @param array $params 参数名值对
	 * @since 1.0
	 */
	function addParams(array $params) {
		$this->params = array_merge($this->params, $params);
	}
	
	/**
	 * 取得参数值
	 *
	 * @param string $name 参数名
	 * @return mixed
	 * @since 1.0
	 */
	function param($name) {
		if (array_key_exists($name, $this->params)) {
			return $this->params[$name];
		}
		
		$post = $this->post($name);
		if (!is_null($post)) {
			return $post;
		}
		
		$get = $this->get($name);
		if (!is_null($get)) {
			return $get;
		}
		
		$cmdOptions = $this->cmdOptions();
		if (isset($cmdOptions["-" . $name])) {
			return $cmdOptions["-" . $name];
		}
		return null;
	}
	
	/**
	 * 取得所有的参数
	 *
	 * @return array
	 * @since 1.0
	 */
	function params() {
		$cmdOptions = $this->cmdOptions();
		$opts = array();
		foreach ($cmdOptions as $name=>$opt) {
			$opts[ltrim($name, "-")] = $opt;
		}
		$params = array_merge($opts, $this->gets());
		$params = array_merge($params, $this->posts());
		$params = array_merge($params, $this->params);
		return $params;
	}
	
	/**
     * 简洁的获取post方法提交过来的值
     * 
     * @param string $name 变量的值
     * @param mixed $default 如未设定，则设为此默认值
     * @return mixed 变量的值
     * @since 1.0
     */
    function post($name, $default = null) {
    	return (isset($_POST[$name]))?$this->strip($_POST[$name], $name):$default;	
    }
    
    /**
     * 简洁的获取get方法提交过来的值
     * 
     * @param string $name 变量的值
     * @param mixed $default 如未设定，则设为此默认值
     * @return mixed 变量的值
     * @since 1.0
     */
    function get($name, $default = null) {
    	return (isset($_GET[$name]))?$this->strip($_GET[$name], $name):$default;	
    }    
    
    /**
	 * 得到系统是否自动对传递的参数进行转义
	 * 
	 * @return boolean  
	 * @since 1.0
	 */
    function magic() {
        return get_magic_quotes_gpc();
    }
    
   /**
	* 根据magic_quotes_gpc的值处理参数值
	* 
	* 如果magic_quotes_gpc为1，则将系统自动给参数值加的转义符去掉
	* 
	* @param string|array $value 值
	* @param string|null $param 参数名
	* @return  string|array 处理结果
	* @since 1.0
	*/
    private function strip($value, $param = null) {
        if (is_array($value)) {
        	foreach ($value as $_param => $_value) {
        		$value[$_param] = $this->strip($_value, is_null($param) ? $_param : $param);
        	}
        }
        else {
        	if ($this->magic()) {
        		$value = stripslashes($value);
        	}
        	$value = $this->filter($param, $value);
        }
        return $value;
    }
	
	/**
	 * 取得命令行传入的参数
	 * 
	 * <code>
	 * 只能接受
	 *   php cmd.php -k=ko -p=po
	 * 的参数，无法分析
	 * 	 php cmd.php -k ko -p po
	 * 要实现后一种命令行的分析，请使用util.cli
	 * </code>
	 *
	 * @return array
	 * @since 1.0
	 */
	function cmdOptions() {
		if (!isset($_SERVER["argv"])) {
			return array();
		}
		$argv = $_SERVER["argv"];
		$options = array();
		if (!empty($argv)) {
			unset($argv[0]);
			foreach ($argv as $option) {
				if (strstr($option, "=")) {
					list($optionName, $optionValue) = explode("=", $option, 2);
					$options[$optionName] = $optionValue;
				}
				else {
					$options[$option] = $option;
				}
			}
		}
		return $options;
	}
	
	/**
	 * 取得所有GET传递的数据
	 *
	 * @return array
	 * @since 1.0
	 */
	function gets() {
		return $this->strip($_GET);
	}
	
	/**
	 * 取得所有POST传递的数据
	 *
	 * @return array
	 * @since 1.0
	 */
	function posts() {
		return $this->strip($_POST);
	}
	
  	/**
     * 得到当前客户端的IP
     * 
     * @return string 当前客户端的IP
     * @since 1.0
     */
    function ip() {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) {
            $ip = getenv("HTTP_CLIENT_IP");
        }
        elseif (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        }
        elseif (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) {
            $ip = getenv("REMOTE_ADDR");
        }
        elseif (isset($_SERVER["REMOTE_ADDR"]) && $_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) {
            $ip = $_SERVER["REMOTE_ADDR"];
        }
        else {
            $ip = "0.0.0.0";
        }
        return $ip;
    }
    
    /**
     * 取得请求的方法
     * 
     * GET, POST, PUT ...
     *
     * @return string|null
     * @since 1.0
     */
    function method() {
    	if (isset($_SERVER["REQUEST_METHOD"])) {
        	return $_SERVER["REQUEST_METHOD"];
    	}
    	return null;
    }
    
    /**
     * 判断是否是命令行下执行
     *
     * @return boolean
     * @since 1.0
     */
    function isCli() {
    	return !isset($_SERVER["SERVER_NAME"]) && !isset($_SERVER["SERVER_ADDR"]);
    }
    
    /**
     * 判断是否为GET方法
     *
     * @return boolean
     * @since 1.0
     */    
    function isGet() {
    	return $this->method() == "GET";
    }
    
    /**
     * 判断是否为POST方法
     *
     * @return boolean
     * @since 1.0
     */ 
    function isPost() {
    	return $this->method() == "POST";
    }
    
    /**
     * 判断是否为PUT方法
     *
     * @return boolean
     * @since 1.0
     */
    function isPut() {
    	return $this->method() == "PUT";
    }
    
    /**
     * 取得正在执行的脚本
     *
     * @return string
     * @since 1.0
     */
    function script() {
    	if (isset($_SERVER["SCRIPT_NAME"])) {
            return $_SERVER["SCRIPT_NAME"];
        }
    	if (isset($_SERVER["PHP_SELF"])) {
            return $_SERVER["PHP_SELF"];
        }
        return null;
    }
    
    /**
     * 取得URI
     *
     * @return string
     * @since 1.0
     */
    function uri() {
		if (isset($_SERVER["REQUEST_URI"])) {
            return $_SERVER["REQUEST_URI"];
        }
        return null;
    }
    
    /**
     * 取得URI对象
     *
     * @return IURI
     * @since 1.0
     */
    function uriObj() {
    	return new IURI($this->uri());
    }
    
    /**
     * 取得输入
     *
     * @return string
     * @since 1.0
     */
    function input() {
    	return file_get_contents("php://input");
    }
    
    /**
     * 删除参数
     * 
     * 不能重设命令行传入的参数
     *
     * @param string $param 参数名
     * @since 1.0
     */
    function remove($param) {
    	if (array_key_exists($param, $this->params)) {
    		unset($this->params[$param]);
    	}
    	if (array_key_exists($param, $_GET)) {
    		unset($_GET[$param]);
    	}
    	if (array_key_exists($param, $_POST)) {
    		unset($_POST[$param]);
    	}
    }
    
    /**
     * 判断是否为AJAX请求
     *
     * @return boolean
     * @since 1.0
     */
    function isAjax() {
    	return if_server("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest";
    }
    
    /**
     * 判断是否为Flash请求
     *
     * @return boolean
     * @since 1.0
     */
    function isFlash() {
    	return if_server("HTTP_USER_AGENT") == "Shockwave Flash";
    }
    
    /**
     * 取得请求的报头信息
     *
     * @return array
     * @since 1.0
     */
    function headers() {
    	if (function_exists("apache_request_headers")) {
    		return apache_request_headers();
    	}
    	$headers = array();
    	foreach ($_SERVER as $key => $value) {
    		if ($key == "PATH") {
    			break;
    		}
    		$key = preg_replace("/^HTTP_/", "", $key);
    		$key = preg_replace("/_(.)/e", "'-'.ucfirst('\\1')",  strtolower($key));
    		$key = ucfirst($key);
    		$headers[$key] = $value;
    	}
    	return $headers;
    }
    
    /**
     * 取得请求的报头信息中的某个参数值
     *
     * @return string|null
     * @since 1.0
     */
    function header($name) {
    	$headers = $this->headers();
    	return isset($headers[$name])?$headers[$name]:null;
    }
    
    /**
     * 判断是否为DELETE方法
     *
     * @return boolean
     * @since 1.0
     */ 
    function isDelete() {
    	return $this->method() == "DELETE";
    }
    
    /**
     * 设置不过滤的参数列表
     * 
     * - $this->request()->noFilter("*") - 所有参数都不过滤
     * - $this->request()->noFilter("title,content") - 不过滤title,content
     * - $this->request()->noFilter(array("title", "content")) - 不过滤title,content
     * 
     * @param string|array $params 参数列表
     * @param boolean $overwrite 是否覆盖原有的参数列表
     * @since 1.0
     */
    function noFilter($params = "*", $overwrite = false) {
    	$this->noFilterParamsHistory = $this->noFilterParams;
    	if (is_string($params)) {
    		$params = explode(",", preg_replace("/\s+/", "", trim($params)));
    	}
    	$this->noFilterParams = $overwrite ? $params : if_array_join($this->noFilterParams, $params);
    }
    
    /**
     * 过滤参数中的特殊字符
     *
     * @param string $param 参数名
     * @param null|scalar $value 参数值
     * @since 1.0
     */
    private function filter($param, $value) {
    	if (is_null($value) || is_numeric($value) || is_bool($value) || in_array("*", $this->noFilterParams) || in_array($param, $this->noFilterParams)) {
    		return $value;
    	}
    	$value = trim($value);
    	$value = htmlspecialchars($value);
    	return $value;
    }
    
    /**
     * 恢复上一次的filter列表
     *
     * @since 1.0.3
     */
    function restoreFilterParams() {
    	$this->noFilterParams = $this->noFilterParamsHistory;
    }
}


?>